package cn.edu.njuit.children.service.impl;

import cn.edu.njuit.children.entity.UserAccount;
import cn.edu.njuit.children.mapper.RoleMapper;
import cn.edu.njuit.children.mapper.UserMapper;
import cn.edu.njuit.children.service.TokenService;
import cn.edu.njuit.children.service.dto.UserToken;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.Date;

/**
 * @Description: TODO
 * @Data: 2022/11/29 10:06
 * @Author: guzy
 */
@Service
public class TokenServiceImpl implements TokenService {
    @Autowired
    UserMapper userMapper;

    @Autowired
    RoleMapper roleMapper;

    @Value("${jwt.secret}")
    String jwtSecret;

    @Override
    public boolean validateToken(String token) {
        //在反解析令牌的过程中，对令牌格式进⾏了校验，可以直接使⽤反解析⽅法进⾏校验
        try {
            this.getUser(token);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public String getToken(String phone) throws Exception {
        //根据登录名查询账户数据对象
        UserAccount user = userMapper.selectOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getPhone,phone));
        if (user != null) {
            //使⽤已配置的秘钥初始化jwt签名⼯具，此处jwtSecret通过@Value注⼊使⽤
            Algorithm algorithm = Algorithm.HMAC256(jwtSecret);
            //使⽤jwt⼯具包创建jwt标准令牌
            String token = JWT.create() //创建令牌
                    .withClaim("phone", phone)//设置数据体，加⼊login登录名信息
                    .withExpiresAt(Instant.now().plusMillis(30 * 60 * 1000))//设置令牌过期时间戳
                    .sign(algorithm);  //设置签名
            return token;
        } else {
            throw new Exception("用户身份错误，未找到用户:" + phone);
        }
    }

    @Override
    public String getPhone(String token) {
        return null;
    }

    @Override
    public UserToken getUser(String token) {
        try{
            //使⽤已配置的秘钥初始化jwt签名⼯具，此处jwtSecret通过@Value注⼊使⽤
            Algorithm algorithm = Algorithm.HMAC256(this.jwtSecret);
            //使⽤签名⼯具，构建jwt验证⼯具。
            JWTVerifier verifier = JWT.require(algorithm).build();
            //通过验证⼯具验证令牌，并得到反解析后的Jwt令牌内容：DecodedJWT对象。
            DecodedJWT jwt = verifier.verify(token);
            //通过Claim声明对象获得⽣成令牌时候声明的login信息
            Claim loginClaim = jwt.getClaim("phone");
            //读取login信息
            String phone = loginClaim.asString();
            //创建令牌⽤户对象
            UserToken userToken = new UserToken();
            //通过roleRepository获取⽤户对应⻆⾊
            userToken.setRoles(roleMapper.findByPhone(phone));
            //设置登录名
            userToken.setLogin(phone);
            //设置过期时间
            userToken.setExpire(jwt.getExpiresAt().getTime());
            return userToken;
        }catch (TokenExpiredException e) {
            throw new RuntimeException("token过期");
        } catch (Exception e) {
            throw new RuntimeException("token验证失败:"+e.getMessage());
        }


    }

}
